package database;

import java.io.FileWriter;
import java.io.IOException;

/**
 * Clase abstracta que representa una pregunta
 * @author Grupo 11 de Programacion Orientada a Objetos
 */

public abstract class Question implements Visitable {
	
	private int score;
	private int level;
	private String questionText;
	
	/**
	 * Método heredado por las subclases concretas
	 * para consultar el nivel de dificultad de una
	 * pregunta.
	 * @return int - dificultad (0, 1, 2)
	 */

	public int getLevel() {
		return level;
	}

	/**
	 * Método heredado por las subclases concretas
	 * para establecer el nivel de dificultad de una
	 * pregunta. De ser un nivel inválido, se establece
	 * en fácil (0)
	 * @param level - dificultad
	 */
	
	public void setLevel(int level) {
		if (level < 0 || level > 2)
			this.level = 0;
		else
			this.level = level;
	}

	/**
	 * Método heredado por las subclases concretas
	 * para consultar el puntaje de una pregunta.
	 * @return int - puntaje
	 */
	
	public int getScore() {
		return score;
	}

	/**
	 * Método heredado por las subclases concretas
	 * para establecer el puntaje de una pregunta,
	 * de ser negativo o 0, se lo establece en 1 por
	 * default
	 * @param score - puntaje
	 */
	
	public void setScore(int score) {
		if (score <= 0)
			this.score = 1;
		else
			this.score = score;
	}

	/**
	 * Método heredado por las subclases concretas
	 * para obtener el texto que se le muestra al usuario
	 * como pregunta.
	 * @return String - Texto de la pregunta mostrada al usuario
	 */
	
	public String getQuestionText() {
		return questionText;
	}

	/**
	 * Método heredado por las subclases concretas
	 * para establecer el texto de la pregunta que
	 * luego es mostrado al usuario.
	 * @param questionText - texto de la pregunta
	 */
	
	public void setQuestionText(String questionText) {
		this.questionText = questionText;
	}
	
	/**
	 * Método que deben sobreescribir las subclases concretas
	 * para retornar un hash de la pregunta 
	 * @return int - hash de la pregunta
	 */

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + level;
		result = prime * result
				+ ((questionText == null) ? 0 : questionText.hashCode());
		return result;
	}
	
	/**
	 * Método que deben sobreescribir las subclases concretas
	 * para poder compararse semánticamente
	 * @return boolean - si son iguales o no
	 */
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Question other = (Question) obj;
		if (level != other.level)
			return false;
		if (questionText == null) {
			if (other.questionText != null)
				return false;
		} else if (!questionText.equals(other.questionText))
			return false;
		return true;
	}
	

	/**
	 * Implementado por las subclases concretas para
	 * definir si una pregunta fue contestada correctamente
	 * @return boolean - Contestada correctamente o no.
	 */
	
	public abstract boolean validAnswer();


	/**
	 * Implementado por las subclases concretas para
	 * poder obtener la pregunta completamente cualificada
	 * en forma de texto
	 * @return String - Texto de la pregunta completamente
	 * cualificada
	 */
	
	public abstract String toString();
	
	/**
	 * Método que implementan las subclases concretas para poder
	 * escribirse a sí mismas en archivo
	 * @param aFile - instancia de FileWriter que indica el archivo
	 * donde deben almacenarse.
	 * @throws IOException - Si falla la escritura.
	 */
	
	public abstract void saveToFile(FileWriter aFile) throws IOException;
}
